package com.security.manage.search.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.security.manage.search.model.*;
import com.security.manage.search.repository.*;
import com.security.manage.search.service.AsynService;
import com.security.manage.search.service.UserMicroService;
import com.security.manage.search.util.FastDfsClient;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@RestController
public class LogController {

    @Resource
    private FileInfoRepository fileInfoRepository;
    @Resource
    private UserMicroService userMicroService;

    @Resource
    private AsynService asynService;

    private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @PostMapping("/file/pc-upload")
    public ResData uploadFile(@RequestParam("file") MultipartFile file){

        String fileName=file.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)){
            return new ResData(0,"参数异常");
        }

        InputStream fileStream = null;
        try {
            fileStream = file.getInputStream();
        } catch (IOException e) {
            return new ResData(0,"数据异常",null);
        }

        if (fileStream==null){
            return new ResData(0,"数据异常",null);
        }

        try {
            return fileUpload(fileStream,fileName);
        } catch (Exception e) {
            return new ResData(0,"删除文件失败",null);
        }
    }

    @PostMapping(value = "/file/upload")
    public ResData singleFileUpload(HttpServletRequest req){

        String fileName=req.getParameter("file");
        if (StringUtils.isEmpty(fileName)){
            return new ResData(0,"参数异常");
        }

        InputStream fileStream = null;
        try {
            fileStream = req.getInputStream();
        } catch (IOException e) {
            return new ResData(0,"数据异常",null);
        }

        if (fileStream==null){
            return new ResData(0,"数据异常",null);
        }

        try {
            return fileUpload(fileStream,fileName);
        } catch (Exception e) {
            return new ResData(0,"上传文件失败",null);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public ResData fileUpload(InputStream fileStream, String fileName) throws Exception{
        FileInfo fileInfo = fileInfoRepository.findByFileName(fileName);
        if (fileInfo!=null){
            return new ResData(0,"文件已经上传过了",null);
        }

        String uKey = fileName.substring(0, fileName.indexOf("-"));
        String password = uKey.substring(1,uKey.length()-1);
        String dateTime = fileName.substring(fileName.indexOf("-")+1,fileName.indexOf(".zip"));
        String dateChange="";
        if (dateTime.contains("_")&&dateTime.contains(".")){
            dateChange = dateTime.substring(dateTime.indexOf(".")+1);
            dateTime = dateTime.substring(0,dateTime.indexOf("."));
        }
        password+=dateTime.substring(dateTime.length()-6);
        LocalDateTime fileTime1 = LocalDateTime.parse(dateTime, dtf);
        LocalDateTime fileTime = asynService.getFinalFileTime(fileTime1,dateChange);
        if (!"".equals(dateChange)){
            dateTime = fileTime.format(dtf);
        }
        fileName = uKey+"-"+dateTime+".zip";
        String data = userMicroService.getData(uKey);
        JSONObject jsonObject = JSON.parseObject(data);
        if (jsonObject.getIntValue("status")==0){
            return new ResData(0,"找不到对于的用户信息");
        }
        JSONObject data1 = jsonObject.getJSONObject("data");
        Long userId = data1.getLong("userId");
        Long deptId = data1.getLong("deptId");
        String tmp = System.getProperty("java.io.tmpdir")+File.separator;
        File file = new File(tmp+fileName);
        copy(file,fileStream);
        String extractPath = fileName.substring(0,fileName.indexOf(".zip"));
        boolean flag = extractFile(tmp+extractPath,file,password);
        if (!flag) {
            return new ResData(0, "解密文件失败，密码错误");
        }
        File directory = new File(tmp+extractPath);
        asynService.asynsUploadFileToFastDfs(fileName,file,userId,deptId,fileTime);
        asynService.parseFile(directory,userId,deptId,uKey,dateTime,fileTime,dateChange);

        return new ResData(1,"上传成功","");

    }


    private boolean extractFile(String zipPath,File file,String password) {

        try {
            ZipFile zFile = new ZipFile(file); // 首先创建ZipFile指向磁盘上的.zip文件
            File destDir = new File(zipPath); // 解压目录
            if (!destDir.exists()) {// 目标目录不存在时，创建该文件夹
                destDir.mkdirs();
            }
            if (zFile.isEncrypted()) {
                zFile.setPassword(password.toCharArray()); // 设置密码
            }
            zFile.extractAll(zipPath); // 将文件抽出到解压目录(解压)
            return true;
        } catch (ZipException e) {
            return false;
        }
    }

    private void copy(File destFile, InputStream zis) throws Exception {
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        int len;
        byte[] buff = new byte[4096];
        while ((len = zis.read(buff, 0 ,4096)) != -1) {
            bos.write(buff, 0, len);
            bos.flush();
        }
        bos.close();
    }





}
